#include "record.h"
#include "format_wav.h"
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <inttypes.h>
#include "esp_err.h"
#include "esp_log.h"
#include "sys_clock.h"

#define RECORD_SAMPLE_RATE     44100  // 标准音频采样率
#define RECORD_SAMPLE_BITS     16
#define RECORD_CHANNEL_NUM     2
#define RECORD_I2S_FORMAT      I2S_CHANNEL_FMT_RIGHT_LEFT
#define RECORD_MAX_TIME_MS     (5*60) // 5分钟限制

#define EXAMPLE_RECORD_TIME_SEC 10

static void record_play_event_callback(audio_player_cb_ctx_t *ctx)
{
    ESP_LOGI(TAG, "ctx->audio_event = %d", ctx->audio_event);

    record_app_data_t* record_app_data = (record_app_data_t *) ctx->user_ctx;

    switch (ctx->audio_event) {
    case AUDIO_PLAYER_CALLBACK_EVENT_IDLE: 
    {  // 播放完一首歌 进入这个case
        ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_IDLE");
        // 指向下一首歌
        if (record_app_data->file_iterator) {
            file_iterator_next(record_app_data->file_iterator);
            int index = file_iterator_get_index(record_app_data->file_iterator);
            ESP_LOGI(TAG, "playing index '%d'", index);
            record_play_index(record_app_data, index);
        }
        break;
    }
    case AUDIO_PLAYER_CALLBACK_EVENT_PLAYING: // 正在播放音乐
        ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_PLAY");
        sys_set_pa_level(1); // 打开音频功放
        break;
    case AUDIO_PLAYER_CALLBACK_EVENT_PAUSE: // 正在暂停音乐
        ESP_LOGI(TAG, "AUDIO_PLAYER_REQUEST_PAUSE");
        sys_set_pa_level(0); // 关闭音频功放
        break;
    default:
        break;
    }
}

int recorder_meida_init(record_app_data_t* record_app_data)
{
    // 创建record目录 (SD卡基地址为/sdcard)
    struct stat st;
    if (stat("/sdcard/record", &st) == -1) {
        mkdir("/sdcard/record", 0777);
    }

    // 分配录音上下文
    record_app_data->record_ctx = (record_ctx_t*)malloc(sizeof(record_ctx_t));
    if (!record_app_data->record_ctx) {
        ESP_LOGE(TAG, "Failed to allocate record context");
        return -1;
    }
    memset(record_app_data->record_ctx, 0, sizeof(record_ctx_t));

    audio_player_callback_register(record_play_event_callback, record_app_data);
    
    return 0;
}

int recorder_meida_deinit(record_app_data_t* record_app_data)
{
    // 安全检查：如果正在录音，先停止录音
    if (record_app_data->record_state == RECORD_STATE_RECORDING) {
        ESP_LOGW(TAG, "Recording in progress, stopping before deinit");
        
        // 更新WAV文件头
        record_app_data->record_ctx->wav_header.descriptor_chunk.chunk_size = 
            record_app_data->record_ctx->data_size + sizeof(wav_header_t) - 8;
        record_app_data->record_ctx->wav_header.data_chunk.subchunk_size = 
            record_app_data->record_ctx->data_size;

        if (xSemaphoreTake(record_app_data->file_mutex, pdMS_TO_TICKS(500)) != pdTRUE) {
            ESP_LOGE(TAG, "Failed to acquire file mutex");
            return -1;
        }
        // 重写文件头
        if (record_app_data->record_ctx->file) {
            fseek(record_app_data->record_ctx->file, 0, SEEK_SET);
            fwrite(&record_app_data->record_ctx->wav_header, sizeof(wav_header_t), 1, 
                  record_app_data->record_ctx->file);
            fclose(record_app_data->record_ctx->file);
            record_app_data->record_ctx->file = NULL;
        }
        xSemaphoreGive(record_app_data->file_mutex);

        record_app_data->record_state = RECORD_STATE_IDLE;
        ESP_LOGI(TAG, "Recording saved to %s (%lu bytes)", 
                record_app_data->record_ctx->filename, record_app_data->record_ctx->data_size);
    }

    // 关闭I2S
    audio_manager_close();

    // 确保文件已关闭并释放内存
    if (record_app_data->record_ctx) {
        if (record_app_data->record_ctx->file) {
            fclose(record_app_data->record_ctx->file);
        }
        free(record_app_data->record_ctx);
        record_app_data->record_ctx = NULL;
    }

    return 0;
}

int recorder_start(record_app_data_t* record_app_data)
{
    if (!record_app_data || !record_app_data->record_ctx) {
        ESP_LOGE(TAG, "Invalid record context");
        return -1;
    }

    // 创建录音文件
    esp_err_t errno = snprintf(record_app_data->record_ctx->filename,
             sizeof(record_app_data->record_ctx->filename),
             "/sdcard/record/rec_%04d%02d%02d_%08d.wav",
             2025, 05, 18, (int)esp_uptime_get_ms());

    record_app_data->record_ctx->file = fopen(record_app_data->record_ctx->filename, "wb");
    if (!record_app_data->record_ctx->file) {
        ESP_LOGE(TAG, "Failed to open file %s (errno: %d)", 
                record_app_data->record_ctx->filename, errno);
        return -1;
    }

    // 初始化WAV头(初始数据大小为0)
    record_app_data->record_ctx->wav_header = 
        WAV_HEADER_PCM_DEFAULT(0, RECORD_SAMPLE_BITS, RECORD_SAMPLE_RATE, RECORD_CHANNEL_NUM);
    
    // 写入初始WAV头
    if (fwrite(&record_app_data->record_ctx->wav_header, sizeof(wav_header_t), 1, 
               record_app_data->record_ctx->file) != 1) {
        ESP_LOGE(TAG, "Failed to write WAV header");
        fclose(record_app_data->record_ctx->file);
        return -1;
    }
    
    if (audio_manager_set_sampling_rate(RECORD_SAMPLE_RATE, RECORD_SAMPLE_BITS, I2S_SLOT_MODE_STEREO) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to open audio input");
        fclose(record_app_data->record_ctx->file);
        return -1;
    }

    // if (audio_manager_set_in_gain(30.0, NULL) != ESP_OK) {
    //     ESP_LOGE(TAG, "Failed to set input gain");
    //     fclose(record_app_data->record_ctx->file);
    //     audio_manager_close();
    //     return -1;
    // }

    record_app_data->record_state = RECORD_STATE_RECORDING;
    record_app_data->record_ctx->data_size = 0;

    // 启动录音定时器
    if (xTimerStart(record_app_data->record_timer, portMAX_DELAY) != pdPASS) {
        ESP_LOGE(TAG, "Failed to start record timer");
        return -1;
    }

    
    ESP_LOGI(TAG, "Recording started to %s", record_app_data->record_ctx->filename);
    return 0;
}

int recorder_pause(record_app_data_t* record_app_data)
{
    if (!record_app_data || record_app_data->record_state != RECORD_STATE_RECORDING) {
        ESP_LOGE(TAG, "Not recording or invalid context");
        return -1;
    }

    // 暂停录音
    record_app_data->record_state = RECORD_STATE_PAUSED;
    ESP_LOGI(TAG, "Recording paused");
    return 0;
}

int recorder_resume(record_app_data_t* record_app_data)
{
    if (!record_app_data || record_app_data->record_state != RECORD_STATE_PAUSED) {
        ESP_LOGE(TAG, "Not paused or invalid context");
        return -1;
    }

    // 恢复录音
    record_app_data->record_state = RECORD_STATE_RECORDING;
    ESP_LOGI(TAG, "Recording resumed");
    return 0;
}

int recorder_stop(record_app_data_t* record_app_data)
{
    if (!record_app_data || 
        (record_app_data->record_state != RECORD_STATE_RECORDING && 
         record_app_data->record_state != RECORD_STATE_PAUSED)) {
        ESP_LOGE(TAG, "Not recording/paused or invalid context");
        return -1;
    }

    // 更新WAV文件头
    record_app_data->record_ctx->wav_header.descriptor_chunk.chunk_size = 
        record_app_data->record_ctx->data_size + sizeof(wav_header_t) - 8;
    record_app_data->record_ctx->wav_header.data_chunk.subchunk_size = 
        record_app_data->record_ctx->data_size;

    if (xSemaphoreTake(record_app_data->file_mutex, pdMS_TO_TICKS(500)) != pdTRUE) {
        ESP_LOGE(TAG, "Failed to acquire file mutex");
        return -1;
    }

    // 重写文件头
    if (record_app_data->record_ctx->file) {
        fseek(record_app_data->record_ctx->file, 0, SEEK_SET);
        fwrite(&record_app_data->record_ctx->wav_header, sizeof(wav_header_t), 1, 
              record_app_data->record_ctx->file);
        fclose(record_app_data->record_ctx->file);
        record_app_data->record_ctx->file = NULL;
    }
    xSemaphoreGive(record_app_data->file_mutex);

    // 停止录音定时器
    if (xTimerStop(record_app_data->record_timer, portMAX_DELAY) != pdPASS) {
        ESP_LOGW(TAG, "Failed to stop data transfer timer");
    }

    // 关闭音频输入
    audio_manager_close();

    record_app_data->record_state = RECORD_STATE_IDLE;

    record_app_data->last_time = 0;
    record_app_data->record_time = 0;
    updata_record_ui_time(record_app_data->record_time);

    ESP_LOGI(TAG, "Recording saved to %s (%lu bytes)", 
            record_app_data->record_ctx->filename, record_app_data->record_ctx->data_size);
    return 0;
}

/**
 * @brief 处理录音数据，建议在主循环中每10-50ms调用一次
 * @param record_app_data 录音应用数据
 * @return 0成功，-1失败
 */
int recorder_process_data(record_app_data_t* record_app_data)
{
    if (!record_app_data || !record_app_data->record_ctx || 
        record_app_data->record_state != RECORD_STATE_RECORDING) {
        return 0;
    }
    
    size_t bytes_read = 0;
    /* 从I2S读取原始采样数据 - 使用较小的缓冲区减少阻塞时间 */
    audio_manager_i2s_read(record_app_data->record_ctx->i2s_readraw_buff, sizeof(record_app_data->record_ctx->i2s_readraw_buff), 
        &bytes_read, 1000);

    if (bytes_read > 0 && record_app_data && record_app_data->record_ctx) {
        if (xSemaphoreTake(record_app_data->file_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
            /* 将采样写入WAV文件 */
            if (record_app_data->record_ctx->file) {
                // 检查文件指针有效性
                if (ftell(record_app_data->record_ctx->file) < 0) {
                    ESP_LOGE(TAG, "Invalid file position");
                    xSemaphoreGive(record_app_data->file_mutex);
                    return -1;
                }
                
                size_t written = fwrite(record_app_data->record_ctx->i2s_readraw_buff, 1, bytes_read, record_app_data->record_ctx->file);
                if (written == bytes_read) {
                    record_app_data->record_ctx->data_size += written;
                } else {
                    ESP_LOGE(TAG, "Failed to write audio data to file (expected:%d, actual:%d)", 
                            bytes_read, written);
                    xSemaphoreGive(record_app_data->file_mutex);
                    return -1;
                }
                
                // 每10次写入刷新一次缓冲区(平衡数据安全性和SD卡寿命)
                static uint8_t flush_counter = 0;
                if (++flush_counter >= 10) {
                    flush_counter = 0;
                    if (fflush(record_app_data->record_ctx->file) != 0) {
                        ESP_LOGE(TAG, "Failed to flush file buffer");
                        xSemaphoreGive(record_app_data->file_mutex);
                        return -1;
                    }
                }
            }
            xSemaphoreGive(record_app_data->file_mutex);
        }
    }

    record_app_data->record_time = (record_app_data->record_ctx->data_size) / 
                                 (RECORD_SAMPLE_RATE * RECORD_CHANNEL_NUM * (RECORD_SAMPLE_BITS/8));  //通过文件大小来计算时长, 单位:秒

    if (record_app_data->record_time != record_app_data->last_time) {
        record_app_data->last_time = record_app_data->record_time;
        ESP_LOGI(TAG, "Recording time: %lu s", record_app_data->record_time);
        updata_record_ui_time(record_app_data->record_time);
    }

    // 检查是否需要暂停或停止
    if (record_app_data->record_state != RECORD_STATE_RECORDING) {
        return 0;
    }

    return 0;
}

void record_play_index(record_app_data_t* record_app_data, int index)
{
    ESP_LOGI(TAG, "play_index(%d)", index);

    char filename[128];
    int retval = file_iterator_get_full_path_from_index(record_app_data->file_iterator, index, filename, sizeof(filename));
    if (retval == 0) {
        ESP_LOGE(TAG, "unable to retrieve filename");
        return ;
    }

    FILE *fp = fopen(filename, "rb");
    if (fp) {
        ESP_LOGI(TAG, "Playing '%s'", filename);
        audio_player_play(fp);
        file_iterator_set_index(record_app_data->file_iterator, index);
        record_app_data->track_no = index;
    } else {
        ESP_LOGE(TAG, "unable to open index %d, filename '%s'", index, filename);
    }
}
